package com.winning.pmph.ctrl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.winning.pmph.entity.*;
import com.winning.pmph.mapper.*;
import com.winning.pmph.service.CalculatorService;
import com.winning.pmph.service.PlatformService;
import com.winning.pmph.service.TagService;
import com.winning.pmph.service.TaskItemService;
import com.winning.pmph.utils.ApplicationContextUtil;
import com.winning.pmph.utils.ExecutorServiceFactory;
import com.winning.pmph.utils.FileStreamUtil;
import com.winning.pmph.utils.PMPHAppUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Api(value = "知识库管理/知识规则")
@Slf4j
@RestController
@RequestMapping("/pmph/action/medicalCalculator")
public class CalculatorCtrl {

    @Resource
    private CalculatorService calculatorService;
    @Resource
    private TagService tagService;
    @Resource
    private KnowledgeSyncRecordMapper knowledgeSyncRecordMapper;
    @Resource
    private KnowledgeSyncStatusMapper knowledgeSyncStatusMapper;
    @Resource
    private HistoryMapper historyMapper;
    @Resource
    private PlatformService platformService;
    @Resource
    private PlatformKnowledgeLibMapper platformKnowledgeLibMapper;
    @Resource
    private TaskItemService taskItemService;
    @Resource
    private ReleasedMedicalCalculatorMapper releasedMedicalCalculatorMapper;

    @ApiOperation(value = "selectMedicalCalculatorList", notes = "医学计算器条件查询确定按钮")
    @GetMapping("selectMedicalCalculatorList")
    public Map<String, Object> selectMedicalCalculatorList(String subject, String name, String status,
                                                           String type, Integer currentPage, Integer pageNum) {
        Map<String, Object> map = new HashMap<>();
        List<MedicalCalculator> list = calculatorService.queryMedicalCalculatorList(currentPage, pageNum, subject, name, status, type);
        for (MedicalCalculator item : list) {
            if (StringUtils.isBlank(item.getTagId())) {
                continue;
            }
            String tagIds = "(" + transferTagId(item.getTagId()).replaceAll("\"", "'").replaceAll("\\[", "").replaceAll("]", "") + ")";
            List<Tag> tagList = tagService.getTagByIds(tagIds);
            if (CollectionUtils.isNotEmpty(tagList)) {
                item.setTagName(tagList.stream().map(Tag::getName).collect(Collectors.joining(",")));
            }
        }
        int totalNum = calculatorService.getMedicalCalculatorTotalNum(subject, name, status, type);
        map.put("totalNum", totalNum);
        map.put("tableData", list);
        return map;
    }

    private String transferTagId(String tagId) {
        tagId = tagId.substring(1, tagId.lastIndexOf("]"));
        if (tagId.indexOf("],") == -1) {
            tagId = tagId.substring(1, tagId.lastIndexOf("]"));
            if (tagId.indexOf(",") == -1) {
                return tagId;
            }
            tagId = tagId.split(",")[tagId.split(",").length - 1];
            return tagId;
        }
        String[] spl = tagId.split("],");
        List<String> stline = new ArrayList<>();
        for (String spStr : spl) {
            stline.add(spStr.split(",")[spStr.split(",").length - 1].replace("]", ""));
        }
        return stline.toString();
    }

    @ApiOperation(value = "deleteCalculator", notes = "删除未发布医学计算器接口-单条")
    @GetMapping("deleteCalculator")
    public void deleteCalculator(String id) {
        boolean result = calculatorService.deleteById(id);
    }

    /**
     * 保存医学计算器
     */
    @ApiOperation(value = "save", notes = "医学计算器保存按钮接口")
    @PostMapping("save")
    public void save(String data, String isReleased, String taskItemId, String nameSuggestion) {
        calculatorService.save(data, Boolean.parseBoolean(isReleased), taskItemId, nameSuggestion);
    }

    /**
     * 保存医学计算器
     */
    @ApiOperation(value = "commit", notes = "医学计算器提交按钮接口")
    @PostMapping("commit")
    public void commit(String data, String taskItemId, String nameSuggestion) {
        calculatorService.commit(data, taskItemId, nameSuggestion);
    }

    @ApiOperation(value = "pass", notes = "医学计算器审核按钮接口")
    @PostMapping("pass")
    public void pass(String data, String nameSuggestion) {
        calculatorService.pass(data, nameSuggestion);
    }

    @ApiOperation(value = "reject", notes = "医学计算器驳回按钮接口")
    @PostMapping("reject")
    public void reject(String data, String rejectReason, String nameSuggestion) {
        calculatorService.reject(data, rejectReason, nameSuggestion);
    }

    @ApiOperation(value = "selectTagData", notes = "医学计算器获取分类接口")
    @GetMapping("selectTagData")
    public List<Map<String, Object>> selectTagData(String tags) {
        log.debug("getTagData called");
        log.debug("获取分类");
        log.debug("tags: " + tags);
        List<Map<String, Object>> resultList = calculatorService.getOptions();
        log.debug("getTagData return");
        return resultList;
    }

    @ApiOperation(value = "selectPlatform", notes = "医学计算器获取平台接口")
    @GetMapping("selectPlatform")
    public List<Map<String, Object>> selectPlatform() {
        List<Map<String, Object>> ruleCascadeList = new ArrayList<>();
        List<Platform> platforms = platformService.lambdaQuery().select(Platform::getId, Platform::getName).list();
        for (Platform platform : platforms) {
            Map<String, Object> tagCascadeMap = new HashMap<>();
            tagCascadeMap.put("value", platform.getId());
            tagCascadeMap.put("label", platform.getName());
            ruleCascadeList.add(tagCascadeMap);
        }
        return ruleCascadeList;
    }

    @ApiOperation(value = "selectDataById", notes = "医学计算器未发布详情接口")
    @GetMapping("selectDataById")
    public Map<String, Object> selectDataById(String id) {
        log.debug("通过ID获取公式数据");
        log.debug("getDataById called");
        log.debug("id: " + id);
        Map<String, Object> dataMap = calculatorService.getCalculatorDataById(id);
        log.debug("getDataById return");
        return dataMap;
    }

    @ApiOperation(value = "selectReleasedCalculatorById", notes = "医学计算器已发布详情接口")
    @GetMapping("selectReleasedCalculatorById")
    public Map<String, Object> selectReleasedCalculatorById(String id) {
        Map<String, Object> dataMap = calculatorService.getReleaseCalculatorDataById(id);
        return dataMap;
    }

    @ApiOperation(value = "selectCalculatorList", notes = "医学计算器查询未发布列表接口")
    @GetMapping("selectCalculatorList")
    public Map<String, Object> selectCalculatorList(String updateTime, String type, String version, String editor,
                                                    String auditor, String name, String platform, String status,
                                                    String subject, Integer currentPage, Integer pageNum) {
        List<MedicalCalculator> list = calculatorService.queryCalculatorList(currentPage, pageNum, status, platform, name, editor, auditor, type, version, updateTime, subject);
        for (MedicalCalculator medicalCalculator : list) {
            // 设置编辑人, 审核人;
            TaskItem lastTaskItem = taskItemService.getPassedTaskItemByKnowledgeId(medicalCalculator.getId());
            if (Objects.nonNull(lastTaskItem)) {
                medicalCalculator.setEditor(lastTaskItem.getEditor());
                List<String> auditorList = Stream.of(lastTaskItem.getFirstAuditor(), lastTaskItem.getSecondAuditor(), lastTaskItem.getThirdAuditor())
                        .filter(StringUtils::isNotEmpty).collect(Collectors.toList());
                medicalCalculator.setAuditorList(auditorList);
            }
        }
        for (MedicalCalculator medicalCalculator : list) {
            if (StringUtils.isBlank(medicalCalculator.getProperty())) {
                continue;
            }
            List<String> platformStr = JSONArray.parseArray(medicalCalculator.getProperty()).toJavaList(String.class);
            List<Platform> platformList = platformService.lambdaQuery().in(Platform::getId, platformStr).list();
            if (CollectionUtils.isNotEmpty(platformList)) {
                medicalCalculator.setProperty(platformList.stream().map(Platform::getName).collect(Collectors.joining(",")));
            }
        }
        int totalNum = calculatorService.getCalculatorTotalNum(status, platform, name, editor, auditor, type, version, updateTime, subject);
        Map<String, Object> map = new HashMap<>();
        map.put("totalNum", totalNum);
        map.put("tableData", list);
        return map;
    }

    @ApiOperation(value = "selectReleasedCalculatorList", notes = "医学计算器查询已发布列表接口")
    @GetMapping("selectReleasedCalculatorList")
    public Map<String, Object> selectReleasedCalculatorList(String updateTime, String type, String version, String editor,
                                                            String auditor, String name, String subject, String platform, String status,
                                                            Integer currentPage, Integer pageNum, Integer isRevised) {
        List<ReleasedMedicalCalculator> list = calculatorService.queryReleasedCalculatorList(currentPage, pageNum, status, platform, name, editor, auditor, type, version, updateTime, subject, isRevised);
        for (ReleasedMedicalCalculator releasedMedicalCalculator : list) {
            // 设置编辑人, 审核人;
            TaskItem lastTaskItem = taskItemService.getLastFinishedTaskItemByKnowledgeId(releasedMedicalCalculator.getId());
            if (Objects.nonNull(lastTaskItem)) {
                releasedMedicalCalculator.setEditor(lastTaskItem.getEditor());
                List<String> auditorList = Stream.of(lastTaskItem.getFirstAuditor(), lastTaskItem.getSecondAuditor(), lastTaskItem.getThirdAuditor())
                        .filter(StringUtils::isNotEmpty).collect(Collectors.toList());
                releasedMedicalCalculator.setAuditorList(auditorList);
            }
            List<TaskItem> taskItemList = taskItemService.getRevisionTaskItemByKnowledgeId(releasedMedicalCalculator.getId());
            if (CollectionUtils.isNotEmpty(taskItemList) && taskItemList.size() > 0) {
                releasedMedicalCalculator.setIsRevised(1);
            }
        }
        for (ReleasedMedicalCalculator releasedMedicalCalculator : list) {
            if (StringUtils.isBlank(releasedMedicalCalculator.getProperty())) {
                continue;
            }
            List<String> platformStr = JSONArray.parseArray(releasedMedicalCalculator.getProperty()).toJavaList(String.class);
            List<Platform> platformList = platformService.lambdaQuery().in(Platform::getId, platformStr).list();
            if (CollectionUtils.isNotEmpty(platformList)) {
                releasedMedicalCalculator.setProperty(platformList.stream().map(Platform::getName).collect(Collectors.joining(",")));
            }
        }
        int totalNum = calculatorService.getReleasedCalculatorTotalNum(status, platform, name, editor, auditor, type, version, updateTime, subject, isRevised);
        Map<String, Object> map = new HashMap<>();
        map.put("totalNum", totalNum);
        map.put("tableData", list);
        return map;
    }

    @ApiOperation(value = "CalculatorToRelease", notes = "医学计算器发布接口")
    @PostMapping("CalculatorToRelease")
    public void CalculatorToRelease(String id) {
        String userName = PMPHAppUtil.getCurrentUserEnName();
        calculatorService.CalculatorToRelease(id, userName);
    }

    @ApiOperation(value = "SelectionCalculatorToRelease", notes = "医学计算器批量发布接口")
    @PostMapping("SelectionCalculatorToRelease")
    public String SelectionCalculatorToRelease(@RequestBody List<String> medicalCalculatorIdList) {
        String userName = PMPHAppUtil.getCurrentUserEnName();
        int nameSuggestionCount = calculatorService.SelectionCalculatorToRelease(medicalCalculatorIdList, userName);
        String resultMsg = "发布成功" + (medicalCalculatorIdList.size() - nameSuggestionCount) + "条数据";
        if (nameSuggestionCount > 0) {
            resultMsg += ", 发布失败" + nameSuggestionCount + "条数据(存在未处理名称修改建议)";
        }
        return resultMsg;
    }

    @ApiOperation(value = "releaseAll", notes = "医学计算器一键发布接口")
    @GetMapping("releaseAll")
    public String releaseAll(String updateTime,
                             String type,
                             String version,
                             String editor,
                             String auditor,
                             String name,
                             String platform,
                             String subject,
                             String status,
                             Integer currentPage, Integer pageSize) {
        List<MedicalCalculator> medicalCalculatorList = calculatorService.queryCalculatorList(currentPage, pageSize, status, platform, name, editor, auditor, type, version, updateTime, subject);
        return SelectionCalculatorToRelease(medicalCalculatorList.stream().map(MedicalCalculator::getId).collect(Collectors.toList()));
    }

    @ApiOperation(value = "selectLogData", notes = "医学计算器查询日志列表接口")
    @GetMapping("selectLogData")
    public List<History> selectLogData(String id) {
        return historyMapper.selectList(Wrappers.lambdaQuery(History.class).eq(History::getKnowledgeId, id)
                .orderByDesc(History::getUpdatedTime).orderByAsc(History::getId));
    }

    @ApiOperation(value = "selectMedicalCalculatorAuditList", notes = "医学计算器审核列表接口")
    @GetMapping("selectMedicalCalculatorAuditList")
    public Map<String, Object> selectMedicalCalculatorAuditList(String name, String subject, String editor, String platform,
                                                                String createdTime, String status, Integer currentPage, Integer pageNum) {
        List<MedicalCalculator> list = calculatorService.queryCalculatorAuditList(currentPage, pageNum, name, subject, editor, platform, createdTime, status);
        for (MedicalCalculator medicalCalculator : list) {
            if (StringUtils.isBlank(medicalCalculator.getProperty())) {
                continue;
            }
            List<String> platformStr = JSONArray.parseArray(medicalCalculator.getProperty()).toJavaList(String.class);
            List<Platform> platformList = platformService.lambdaQuery().in(Platform::getId, platformStr).list();
            if (CollectionUtils.isNotEmpty(platformList)) {
                medicalCalculator.setProperty(platformList.stream().map(Platform::getName).collect(Collectors.joining(",")));
            }
        }
        int totalNum = calculatorService.getCalculatorAuditTotalNum(name, subject, editor, platform, createdTime, status);
        Map<String, Object> map = new HashMap<>();
        map.put("totalNum", totalNum);
        map.put("tableData", list);
        return map;
    }

    @ApiOperation(value = "rejectCalculator", notes = "医学计算器驳回接口")
    @GetMapping("rejectCalculator")
    public void rejectCalculator(String id, String reject) {
        calculatorService.saveRejectReason(id, reject);
    }

    @ApiOperation(value = "selectCalculatorField", notes = "获取医学计算器字段接口")
    @GetMapping("selectCalculatorField")
    public Map<String, Object> selectCalculatorField() {
        List<MedicalCalculatorLibField> fields = calculatorService.getMedicalCalculatorLibField();
        String id = fields.get(0).getKnowledgeLibId();
        String sql = "select * from medical_calculator_lib_field where knowledge_Lib_id='" + id + "' order by kind";
        List<MedicalCalculatorLibField> calculatorLibFields = calculatorService.getMedicalCalculatorLibFieldSql(sql);

        Map<String, Object> resultMap = new HashMap<>();
        List<Map<String, Object>> fieldList = new ArrayList<>();
        for (MedicalCalculatorLibField medicalCalculatorLibField : calculatorLibFields) {
            Map<String, Object> fieldMap = new HashMap<>();
            if (medicalCalculatorLibField.getKind() == MedicalCalculatorField.CASCADE) {
                fieldMap.put("name", medicalCalculatorLibField.getName());
                fieldMap.put("kind", medicalCalculatorLibField.getKind());
                fieldMap.put("property", "");
                fieldMap.put("ident", medicalCalculatorLibField.getIdent());
                fieldMap.put("field_id", medicalCalculatorLibField.getId());
                List<Map<String, Object>> resultList = calculatorService.getSubjectOptions(medicalCalculatorLibField.getTagId());
                fieldMap.put("tagId", resultList);
            } else {
                fieldMap.put("name", medicalCalculatorLibField.getName());
                fieldMap.put("kind", medicalCalculatorLibField.getKind());
                fieldMap.put("property", "");
                fieldMap.put("ident", medicalCalculatorLibField.getIdent());
                fieldMap.put("field_id", medicalCalculatorLibField.getId());
            }
            fieldList.add(fieldMap);
        }
        resultMap.put("id", IdWorker.getIdStr());
        resultMap.put("fields", fieldList);
        return resultMap;
    }

    @ApiOperation(value = "selectOneLevelTag", notes = "医学计算器设置页面获取一级分类接口")
    @GetMapping("selectOneLevelTag")
    public List<Map<String, Object>> selectOneLevelTag() {
        List<Tag> tags = tagService.getBaseMapper().selectList(new QueryWrapper<Tag>().eq("LEVEL", 1));
        List<Map<String, Object>> tagList = new ArrayList<>();
        for (Tag tag : tags) {
            Map<String, Object> tagMap = new HashMap<>();
            tagMap.put("value", tag.getId());
            tagMap.put("label", tag.getName());
            tagList.add(tagMap);
        }
        return tagList;
    }

    @ApiOperation(value = "saveCalculatorLibField", notes = "医学计算器设置页面保存接口")
    @PostMapping("saveCalculatorLibField")
    public Boolean saveCalculatorLibField(String platform, String tableData) {
        return calculatorService.saveCalculatorField(platform, tableData);
    }

    @ApiOperation(value = "selectCalculatorTableData", notes = "医学计算器设置页面列表接口")
    @GetMapping("selectCalculatorTableData")
    public Map<String, Object> selectCalculatorTableData() {
        String sql = "select * from medical_calculator_lib_field where ident=1";
        List<MedicalCalculatorLibField> medicalCalculatorLibFields = calculatorService.getMedicalCalculatorLibFieldSql(sql);
        List<MedicalCalculatorLibField> fields = calculatorService.getMedicalCalculatorLibField();
        String id = fields.get(0).getKnowledgeLibId();
        String platformSql = "select* from platform_knowledge_lib where knowledge_lib_id ='" + id + "'";
        List<PlatformKnowledgeLib> platformKnowledgeLibList = platformKnowledgeLibMapper.executeMultiSelect(platformSql);
        String platformId = "";
        if (platformKnowledgeLibList.size() > 0) {
            platformId = platformKnowledgeLibList.stream().map(PlatformKnowledgeLib::getPlatformId).collect(Collectors.joining("\",\"", "[\"", "\"]"));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("medicalCalculatorLibFields", medicalCalculatorLibFields);
        map.put("platform", platformId);
        return map;
    }

    @ApiOperation(value = "selectSubject", notes = "医学计算器搜索条件学科分类学接口")
    @GetMapping("selectSubject")
    public Map<String, Object> selectSubject() {
        List<MedicalCalculatorLibField> fields = calculatorService.getMedicalCalculatorLibField();
        String id = fields.get(0).getKnowledgeLibId();
        String sql = "select * from medical_calculator_lib_field where knowledge_Lib_id='" + id + "'" + " and kind =" + MedicalCalculatorField.CASCADE;
        List<MedicalCalculatorLibField> calculatorLibFields = calculatorService.getMedicalCalculatorLibFieldSql(sql);

        Map<String, Object> resultMap = new HashMap<>();
        List<Map<String, Object>> fieldList = new ArrayList<>();
        for (MedicalCalculatorLibField medicalCalculatorLibField : calculatorLibFields) {
            Map<String, Object> fieldMap = new HashMap<>();
            if (medicalCalculatorLibField.getKind() == MedicalCalculatorField.CASCADE) {
                fieldMap.put("name", medicalCalculatorLibField.getName());
                fieldMap.put("kind", medicalCalculatorLibField.getKind());
                fieldMap.put("property", "");
                fieldMap.put("ident", medicalCalculatorLibField.getIdent());
                fieldMap.put("field_id", medicalCalculatorLibField.getId());
                List<Map<String, Object>> resultList = calculatorService.getSubjectOptions(medicalCalculatorLibField.getTagId());
                fieldMap.put("tagId", resultList);
            }
            fieldList.add(fieldMap);
        }
        resultMap.put("fields", fieldList);
        return resultMap;
    }

    @ApiOperation(value = "selectSyncList", notes = "医学计算器同步页面列表接口")
    @GetMapping("selectSyncList")
    public Map<String, Object> selectSyncList(String name,
                                              String subject,
                                              String platform,
                                              String type,
                                              String createTime,
                                              String syncStatus,
                                              String bindingPlatform,
                                              int currentPage,
                                              int pageNum) {
        List<ReleasedMedicalCalculator> list = calculatorService.querySyncCalculatorList(currentPage, pageNum, name, subject, platform, type, createTime, syncStatus, bindingPlatform);
        int totalNum = calculatorService.getSyncCalculatorTotalNum(name, subject, platform, type, createTime, syncStatus, bindingPlatform);
        for (ReleasedMedicalCalculator medicalCalculator : list) {
            if (StringUtils.isBlank(medicalCalculator.getProperty())) {
                continue;
            }
            List<String> platformStr = JSONArray.parseArray(medicalCalculator.getProperty()).toJavaList(String.class);
            List<Platform> platformList = platformService.lambdaQuery().in(Platform::getId, platformStr).list();
            if (CollectionUtils.isNotEmpty(platformList)) {
                medicalCalculator.setProperty(platformList.stream().map(Platform::getName).collect(Collectors.joining(";")));
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("totalNum", totalNum);
        map.put("tableData", list);
        return map;
    }

    @ApiOperation(value = "selectSyncFailure", notes = "医学计算器推送失败列表接口")
    @GetMapping("selectSyncFailure")
    public Map<String, Object> selectSyncFailure(String name, String kind, String platformId, String operatedTime,
                                                 Integer currentPage, Integer pageNum) {
        List<KnowledgeSyncStatus> list = calculatorService.queryKnowledgeSyncStatusList(currentPage, pageNum, name, kind, platformId, operatedTime);
        int totalNum = calculatorService.getKnowledgeSyncStatusTotalNum(name, kind, platformId, operatedTime);
        Map<String, Object> map = new HashMap<>();
        map.put("tableData", list);
        map.put("totalNum", totalNum);
        return map;
    }

    @ApiOperation(value = "selectSyncLog", notes = "医学计算器同步页面查看日志接口")
    @GetMapping("selectSyncLog")
    public List<KnowledgeSyncRecord> selectSyncLog(String id) {
        List<KnowledgeSyncRecord> knowledgeSyncRecords = knowledgeSyncRecordMapper.lambdaQuery().eq(KnowledgeSyncRecord::getKnowledgeId, id).orderByDesc(KnowledgeSyncRecord::getOperatedTime).list();
        for (KnowledgeSyncRecord knowledgeSyncRecord : knowledgeSyncRecords) {
            List<Platform> platformList = platformService.lambdaQuery().eq(Platform::getId, knowledgeSyncRecord.getPlatformId()).list();
            if (CollectionUtils.isNotEmpty(platformList)) {
                knowledgeSyncRecord.setPlatformId(platformList.stream().map(Platform::getName).collect(Collectors.joining(",")));
            }
        }
        return knowledgeSyncRecords;
    }

    @ApiOperation(value = "syncCalculator", notes = "医学计算器推送接口")
    @GetMapping("syncCalculator")
    public void syncCalculator(String platformIds, String calculatorIds, String syncType) {
        if (Objects.equals("all", syncType)) {
            List<ReleasedMedicalCalculator> releasedMedicalCalculatorList = calculatorService.getReleasedMedicalCalculator();
            calculatorIds = releasedMedicalCalculatorList.stream().map(item -> item.getId()).collect(Collectors.joining(","));
        }
        calculatorService.syncCalculator(platformIds, calculatorIds);
    }

    @ApiOperation(value = "syncAllCalculator", notes = "医学计算器一键推送接口")
    @GetMapping("syncAllCalculator")
    public void syncAllCalculator() {
        List<MedicalCalculatorLibField> medicalCalculatorLibFields = calculatorService.getMedicalCalculatorLibField();
        String sql = "select* from knowledge_sync_status where knowledge_lib_id='" + medicalCalculatorLibFields.get(0).getKnowledgeLibId() + "'" + " and kind =0 or kind=1";
        List<KnowledgeSyncStatus> knowledgeSyncStatusArray = knowledgeSyncStatusMapper.executeMultiSelect(sql);
        for (KnowledgeSyncStatus knowledgeSyncStatus : knowledgeSyncStatusArray) {
            calculatorService.syncCalculator(knowledgeSyncStatus.getPlatformId(), knowledgeSyncStatus.getKnowledgeId());
        }
    }

    @ApiOperation(value = "exportH5", notes = "医学计算器发布列表导出接口")
    @GetMapping("exportH5")
    public void exportH5(String ids, HttpServletResponse response, String updateTime,
                         String type, String version, String editor, String auditor,
                         String name, String platform, String status) {
        response.setContentType("application/zip");// 指明response的返回对象是文件流
        response.setHeader("Content-Disposition", "attachment;filename=export.zip");
        response.reset();
        if (StringUtils.isBlank(ids)) {
            List<ReleasedMedicalCalculator> list = calculatorService.queryExportReleasedCalculatorList(status, platform, name, editor, auditor, type, version, updateTime);
            ids = list.stream().map(ReleasedMedicalCalculator::getId).collect(Collectors.joining(","));
        }
        // 读取模板;
        ZipOutputStream zipOutputStream = null;
        try {
            zipOutputStream = new ZipOutputStream(response.getOutputStream());
            ClassPathResource templateFileResource = new ClassPathResource("public/calculator/export-template.html");
            String templateStr = new String(FileStreamUtil.inputStreamToByte(templateFileResource.getInputStream()), "utf8");
//            File templateFile = ResourceUtils.getFile("classpath:public/calculator/export-template.html");
            Document template = Jsoup.parse(templateStr);
            ClassPathResource classPathResource = null;
            // 写入css模板;
            ZipEntry zipEntry = new ZipEntry("export-template.css");
            zipOutputStream.putNextEntry(zipEntry);
            classPathResource = new ClassPathResource("public/calculator/export-template.css");
            zipOutputStream.write(FileStreamUtil.inputStreamToByte(classPathResource.getInputStream()));
            zipEntry = new ZipEntry("index.css");
            zipOutputStream.putNextEntry(zipEntry);
            classPathResource = new ClassPathResource("public/calculator/index.css");
            zipOutputStream.write(FileStreamUtil.inputStreamToByte(classPathResource.getInputStream()));
            zipEntry = new ZipEntry("index.js");
            zipOutputStream.putNextEntry(zipEntry);
            classPathResource = new ClassPathResource("public/calculator/index.js");
            zipOutputStream.write(FileStreamUtil.inputStreamToByte(classPathResource.getInputStream()));
            zipEntry = new ZipEntry("vue.js");
            zipOutputStream.putNextEntry(zipEntry);
            classPathResource = new ClassPathResource("public/calculator/vue.js");
            zipOutputStream.write(FileStreamUtil.inputStreamToByte(classPathResource.getInputStream()));
//            zipEntry = new ZipEntry("crypto-js.min.js");
//            zipOutputStream.putNextEntry(zipEntry);
//            classPathResource = new ClassPathResource("public/calculator/crypto-js.min.js");
//            zipOutputStream.write(FileStreamUtil.inputStreamToByte(classPathResource.getInputStream()));
            List<Map<String, Object>> formulaDataList = new ArrayList<>();
            if (StringUtils.isNotBlank(ids)) {
                for (String id : ids.split(",")) {
                    Map<String, Object> formulaData = calculatorService.getReleaseCalculatorDataById(id);
                    formulaDataList.add(formulaData);
                }
            } else {
                formulaDataList = calculatorService.getAllFormulaData();
            }

            // 不做文件名处理，跟发布时生成的html文件路径保持一直，如果发布时生成的html页面有问题，可以通过该方法重新生成
            for (Map<String, Object> formulaData : formulaDataList) {
                //重新生成html 需要注掉此行代码
                replaceSrc(formulaData);
                //后期可能会用到
                //template.body().child(0).text("let data = \"" + MD5Utils.aesEncryptToBytes(JSON.toJSONString(formulaData)) + "\"");
                template.body().child(0).text("let data = " + JSON.toJSONString(formulaData));
                zipEntry = new ZipEntry(formulaData.get("id") + ".html");
                zipOutputStream.putNextEntry(zipEntry);
                zipOutputStream.write(StringEscapeUtils.unescapeHtml(template.html()).getBytes());
            }
        } catch (Exception e) {
            log.error(null, e);
            throw new RuntimeException(e.getMessage());
        } finally {
            if (null != zipOutputStream) {
                try {
                    zipOutputStream.closeEntry();
                    zipOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void replaceSrc(Map<String, Object> formulaData) {
        String fields = JSONArray.toJSONString(formulaData.get("fields"));
        String describeContent = getFieldImg(formulaData.get("describeContent").toString());
        List<MedicalCalculatorField> medicalCalculatorFields = JSONArray.parseArray(fields, MedicalCalculatorField.class);
        medicalCalculatorFields.stream().filter(t -> t.getKind() == MedicalCalculatorField.TEXT_FIELD).forEach(field -> {
            field.setProperty(getFieldImg(field.getProperty()));
        });
        formulaData.put("describeContent", describeContent);
        formulaData.put("fields", medicalCalculatorFields);
    }

    private String getFieldImg(String property) {
        Document doc = Jsoup.parse(property);
        // 循环遍历所有节点
        String html = "";
        for (Element element : doc.body().getAllElements()) {
            if (element.tagName().equalsIgnoreCase("img")) {
                String imgSrc = element.attr("src");
                element.attr("src", ApplicationContextUtil.getProperty("static-file.path") + imgSrc);
            }
            html = Jsoup.parse(doc.body().html()).body().html();
        }

        return html;
    }

    @ApiOperation(value = "multiInsertTaskItem", notes = "医学计算器修订接口")
    @PostMapping("multiInsertTaskItem")
    public String multiInsertTaskItem(String reviseType, String selectedKnowledgeIds, String taskId,
                                      String remark, String searchParams) {
        JSONObject searchParamsObj = JSON.parseObject(searchParams);
        String username = PMPHAppUtil.getCurrentUserEnName();
        List<ReleasedMedicalCalculator> medicalCalculatorList = null;
        // 批量修订;
        if (Objects.equals("multi", reviseType)) {
            medicalCalculatorList = releasedMedicalCalculatorMapper.selectBeansByWherePart(" id in " + selectedKnowledgeIds.replace("[", "(").replace("]", ")"));
        }
        // 一键修订, 查询当前搜索条件的知识;
        else {
            medicalCalculatorList = calculatorService.queryReleasedCalculatorList(0, 0,
                    searchParamsObj.getString("status"),
                    searchParamsObj.getString("platform"),
                    searchParamsObj.getString("name"),
                    searchParamsObj.getString("editor"),
                    searchParamsObj.getString("auditor"),
                    searchParamsObj.getString("type"),
                    searchParamsObj.getString("version"),
                    searchParamsObj.getString("updateTime"),
                    searchParamsObj.getString("subject"),
                    searchParamsObj.getInteger("isRevised"));
        }
        // 查询正在编辑的计算器;
        String sql = "select * from task_item " +
                " join task on task_item.task_id = task.id " +
                " where task.knowledge_lib_id = '" + KnowledgeLib.CALCULATOR_LIB_ID + "' " +
                " and task.status != " + Task.STATUS_FINISHED +
                " and task.deleted = 0 " +
                " and task_item.status != " + TaskItem.STATUS_RELEASED;
        List<TaskItem> taskItems = taskItemService.getBaseMapper().executeMultiSelect(sql);
        // taskItems 转为知识id集合
        Set<String> knowledgeInProcessIdSet = taskItems.stream().map(TaskItem::getKnowledgeId).filter(org.apache.commons.lang3.StringUtils::isNotEmpty).collect(Collectors.toSet());
        List<ReleasedMedicalCalculator> finalMedicalCalculatorList = medicalCalculatorList;
        List<String> revisedSuccessList = new ArrayList<>();
        List<String> revisedFailureList = new ArrayList<>();
        for (ReleasedMedicalCalculator releasedMedicalCalculator : finalMedicalCalculatorList) {
            if (!knowledgeInProcessIdSet.contains(releasedMedicalCalculator.getId())) {
                revisedSuccessList.add(releasedMedicalCalculator.getId());
            } else {
                revisedFailureList.add(releasedMedicalCalculator.getId());
            }
        }
        ExecutorServiceFactory.getInstance().submit(() -> calculatorService.multiInsertTaskItem(taskId, remark, username, finalMedicalCalculatorList, knowledgeInProcessIdSet));

        return "修订成功！您修订知识" + revisedSuccessList.size() + "条,请稍后查看任务状态,处在已修订的知识为" + revisedFailureList.size() + "条";
    }

    @ApiOperation(value = "deleteReleaseCalcById", notes = "医学计算器发布删除接口")
    @GetMapping("deleteReleaseCalcById")
    public void deleteReleaseCalcById(String id, String status) {
        calculatorService.ReleasedCalcDeleteById(id, status);
    }

    @ApiOperation(value = "selectRecycleData", notes = "查询医学计算器回收站列表接口")
    @GetMapping("selectRecycleData")
    public Map<String, Object> selectRecycleData(Integer currentPage, Integer pageNum, String name,
                                                 String updatedTime, String updatedBy) {
        Page<ReleasedMedicalCalculator> releasedMedicalCalculatorPage = calculatorService.ReleasedCalcDeleteData(currentPage, pageNum, name, updatedTime, updatedBy);
        Map<String, Object> map = new HashMap<>();
        map.put("totalNum", releasedMedicalCalculatorPage.getTotal());
        map.put("tableData", releasedMedicalCalculatorPage.getRecords());
        return map;
    }

    @ApiOperation(value = "recoverReleaseCalc", notes = "医学计算器回收站列表恢复接口")
    @PostMapping("recoverReleaseCalc")
    public void recoverReleaseCalc(String ids) {
        calculatorService.recoverReleasedMedicalCalculator(ids);
    }

    @ApiOperation(value = "delReleasedCalculator", notes = "医学计算器回收站彻底删除接口")
    @PostMapping("delReleasedCalculator")
    public void delReleasedCalculator(String id, String name, String updatedTime, String updatedBy, String operationType) {
        calculatorService.deleteReleasedMedicalCalculator(id, name, updatedTime, updatedBy, operationType);
    }
}
